Regulární výrazy |
PSPad od verze 3.6.0 podporuje hledání pomocí regulárních výrazů
Co jsou to regulární výrazy ?
Regulární výrazy jsou mocný nástroj pro hledání textových řetězců pomocí vzorů. Speciální předdefinované metaznaky dovolují specifikovat, zda hledaný řetězec leží na začátku nebo na konci textu / řádku, umožňuje specifikovat znaky, který řetězec obsahuje apod.
Z počátku vám to určitě bude připadat složité, ale po seznámení zjistíte, že je to velmi užitečný nástroj.
Jednoduché znaky
Každý znak zastupuje sebe. Je to jako při normálním hledání. Pokud zadáte slovo jelen, bude se hledat "jelen". Escape sekvence začíná znakem \. Existují některé speciální znaky, např. ^, který znamená, že se bude hledat na začátku řádku. Pokud ale budete chtít přímo znak ^, musíte zadat \^. Podobně pro hledání samotného znaku \ je třeba zadat \\.
Escape sekvence
Znaky můžou být specifikovány pomocí escape sekvence. \n je nový řádek, \t tabulátor apod. Znaky je možné také zadat pomocí jejich ASCII hodnoty. \xnn je hledání znaku, kde nn je jeho ASCII hodnota vyjádřená v šestnáctkové soustavě.
\xnn znak s šestnáctkovou ASCII hodnotou nn
\t tabulátor (stejné jako \x09
\n nový řádek, stejné jako \x0a
\r CR, stejné jako \x0d
\f FF, stejné jako \x0c
\a BEL, stejné jako \x07
\e ESC, stejné jako \x1b
Příklady:
jel\x20en najde slovo "jel en" (s mezerou uprostřed)
\tjelen najde slovo "jelen", před kterým je tabulátor
Skupiny (třídy) znaků
Je možné specifikovat skupiny znaků. Tato skupina je uzavřena v []. Text bude nalezen, pokud vyhovuje jeden znak ze seznamu. Pokud první znak za závorkou je ^, znamená to, že v textu nesmí být obsažen žádný znak ze seznamu.
Příklady:
jel[aei]n najde slova "jelan", "jelen", "jelin"
jel[^ai]n najde slovo "jelen", ale nenajde "jelin", "jelan" atd.
Znak - znamená rozsah znaků. Potom a-z znamená jakýkoliv znak v rozsahu "a" až "z".
Pokud chcete hledat znak - samotný, je třeba jej uvést na začátku / konci seznamu, nebo jej uvést pomocí \.
Příklady:
[-az] vyhovují znaky "a", "z" a "-"
[az-] vyhovují znaky "a", "z" a "-"
[a\-z] vyhovují znaky "a", "z" a "-"
[a-z] vyhovují všechny znaky v rozsahu "a" až "z"
[\n-\x0D] vyhovují znaky s ASCII hodnotou #10,#11,#12,#13
[\d-t] vyhovují čísla, "-" a "t"
[]-a] vyhovuje znak v rozsahu "]" až "a"
Metaznaky - oddělovače řádků
^ začátek řádku
$ konec řádku
\A začátek textu
\Z konec textu
. jakýkoliv znak
Příklady:
^jelen "jelen", ale pouze pokud je na začátku řádku
jelen$ "jelen", ale pouze pokud je na konci řádku
^jelen$ "jelen", ale pouze pokud na řádku není nic jiného
jele.n "jel"jakýkoliv_znak"n"
Metaznaky - předdefinované skupiny
\w písmena včetně "_"
\W čísla a písmena
\d čísla
\D nečíselné znaky
\s jakákoliv mezera (stejné jako [ \t\n\r\f])
\S nemezerový znak
Příklady:
jel\dn znamená "jel1n", "jel7n", ale ne "jelen"
jel[\w\s]n znamená "jelen", "jel n", ale ne "jel2n", "jel=n" apod.
Metaznaky - čítače
Jakýkoliv znak může být následován čítačem. Lze tak určit počet výskytů předchozího znaku, metaznaku nebo výrazu.
hladové
* žádný nebo více výskytů znaku, podobně jako {0,}
+ jeden nebo více výskytů znaku, podobně jako {1,}
? žádný nebo jeden výskyt znaku, podobně jako {0,1}
{n} přesně n výskytů
{n,} nejméně n výskytů
{n,m} nejméně n-krát, ale ne víc než m-krát
nehladové
*? žádný nebo více výskytů, podobně jako {0,}?
+? jeden nebo více výskytů, podobně jako {1,}?
?? žádný nebo jeden výskyt, podobně jako {0,1}?
{n}? přesně n výskytů
{n,}? nejméně n výskytů
{n,m}? nejméně n-krát, ale ne víc než m-krát
Příklady:
jel.*n najde "jelen", "jel87hsgdn", "jeln"...
jel.+n najde "jelen", "jel87hsgdn", ale ne "jeln"
jel.?n najde "jelen", "jeln", ale ne "jel87hsgdn"
jele{2}n najde "jeleen"
jele{2,}n najde "jeleen", "jeleeen", "jeleeeen"...
jele{2,3}n najde "jeleen", "jeleeen", ale ne "jeleeeen"
Malé vysvětlení o "hladovosti". "Hladový" vrací tolik, kolik je možné. "Nehladový" vrací tak málo, jak je možné. Např. b+ a b* aplikované na řetězec 'abbbbc' vrací 'bbbb', b+? vrací 'b', b*? vrátí prázdný řetězec, b{2,3}? vrátí 'bb', b{2,3} vrátí 'bbb'.
Metaznaky - alternativy
Ve vzoru lze také specifikovat sérii alternativ, jako oddělovač slouží znak |.
Např. jelen|jelan|jelin najde "jelen", "jelan" nebo "jelin" (podobně jako jel(e|a|i)n)
Nezapomeňte ale na to, že znak | uvnitř [] je interpretován jako obyčejný znak !
Pokud tedy uvedete [jelen|jelan|jelin], ve skutečnosti jste zadali, že chcete hledat jeden ze znaků "jeln|ai"
Příklad:
jel(en|ínek) najde "jelen" nebo "jelínek"
Metaznaky - vnořené výrazy
Konstrukce (...) může být použita také pro definici vnořených výrazů.
Příklady:
(jelen){8,10} najde řetězec, který obsahuje 8, 9 nebo 10 výskytů "jelen"
jel([0-9]|e+)n najde "jel0n", "jel3n", "jelen", "jeleen", "jeleeen" ...
Metaznaky - zpětné reference
Metaznaky od \1 do \9 jsou interpretovány jako zpětná reference.
Příklady:
(.)\1+ najde "aaaa" a "cc" (2 a více stejných znaků)
(.+)\1+ najde "abab" a "123123" (opakující se posloupnosti znaků)
(['"]?)(\d+)\1 najde '"13" (v dvojitých uvozovkách) nebo '4' (v jednoduchých uvozovkách) nebo 77
Pár příkladů z praxe:
Hledání
Nahrazování
regulární výrazy umožňují použít v nahrazování i části hledaných řetězců. Shluky znaků, uzavřené v závorkách v části hledat jsou vráceny v proměnných $1..$n, takže je možné je použít v nahradit. Viz následující příklady:
hledat: ([0-9]{2}).([0-9]{2}).([0-9]{4})
nahradit: $3-$2-$1
hledat: ([0-9]{2}):([0-9]{2})
nahradit: $2-$1
hledat: ;
nahradit: \n
upozornění: kurzor na konec textu a hledat směrem "vzad"
hledat: \s+
nahradit: \n
upozornění: kurzor na konec textu a hledat směrem "vzad"
Komplexnější případ z praxe
Měl jsem seznam tagů ve tvaru tag - popis
Potřeboval jsem jej dostat do definice pole ve tvaru a[index] := 'tag';
Pro vysvětlení syntaxe byl použit (přeložen) text z nápovědy k implementaci regulárních výrazů od Andrey V. Sorokina (http://regexpstudio.com/)